//--------------------------------------------------------------------------------
// This file is a portion of the PracticeEngine Rendering Engine.  It is distributed
// under the MIT License, available in the root of this distribution and 
// at the following URL:
//
// http://www.opensource.org/licenses/mit-license.php
//
// Copyright (c) Ferdinand Li 
//--------------------------------------------------------------------------------

#include "PCH.h"
#include <windows.h>
#include "Camera.h"
#include "Logger.h"

using namespace PracEng;

void Camera::SetProjParames(float fFOV, float fAspect, float fNearPlane, float fFarPlane)
{
	this->fNearPlane = fNearPlane;
	this->fFarPlane = fFarPlane;
	this->fAspectRatio = fAspect;
	this->fFov = fFOV;
	mPerspective = PEMatrix::MakePerspectiveMatrix(fFOV, fAspect, fNearPlane, fFarPlane);
}

void Camera::SetViewParams(PEVector3* pEyePt, PEVector3* pLookatPt, PEVector3* pLookUp)
{
	mView = PEMatrix::MakeLookAtLHMatrix(pEyePt, pLookatPt, pLookUp);
}

void Camera::Move(PEVector3& moveDelta)
{
	mMoveDelta = moveDelta;
}

void Camera::Rotate(PEFloat2& rotDelta)
{
	m_fCameraYawAngle += rotDelta.X;
	m_fCameraPitchAngle += rotDelta.Y;

	m_fCameraPitchAngle = __max(-PracEng_PI / 2.0f, m_fCameraPitchAngle);
	m_fCameraPitchAngle = __min(+PracEng_PI / 2.0f, m_fCameraPitchAngle);

	while (m_fCameraYawAngle > PracEng_2PI)
	{
		m_fCameraYawAngle -= PracEng_2PI;
	}
	while (m_fCameraYawAngle < -PracEng_2PI)
	{
		m_fCameraYawAngle = PracEng_2PI + m_fCameraYawAngle;
	}

	PEVector4 PitchYawRoll(m_fCameraPitchAngle, m_fCameraYawAngle, 0.0f, 0.0f);
	mCamRot = PEMatrix::SetRotationYawPitchRoll(PitchYawRoll);

	PEVector4 vLocalUp = PEVector4(0, 1, 0, 0);
	PEVector4 vLocalAhead = PEVector4(0, 0, 1, 0);

	mWorldUp = mCamRot * vLocalUp;
	mWorldAhead = mCamRot * vLocalAhead;
	
}

void Camera::Tick(double DeltaTime)
{
	PEVector3 LookPt(mWorldAhead.x, mWorldAhead.y, mWorldAhead.z);
	LookPt.Normalize();
	PEVector3 WorldUp(mWorldUp.x, mWorldUp.y, mWorldUp.z);
	WorldUp.Normalize();
	PEVector4 MoveDelta(mMoveDelta);

	mWorldMoveDelta = mCamRot * MoveDelta;

	mEyeLocation.x += mWorldMoveDelta.x;
	mEyeLocation.y += mWorldMoveDelta.y;
	mEyeLocation.z += mWorldMoveDelta.z;

	LookPt = mEyeLocation + LookPt;
	SetViewParams(&mEyeLocation, &LookPt, &WorldUp);
}

PracEng::Camera::Camera()
{
	m_fCameraYawAngle = .0f;
	m_fCameraPitchAngle = .0f;
	mCamRot = PEMatrix::GetIdentityMatrix();
	mWorldUp = PEVector4(0.f, .1f, .0f, .0f);
	mWorldAhead = PEVector4(0.f, .0f, .1f, .0f);
}
